//-----------------------------------------------------------------------------
// Copyright (C) 2017 Merlok
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// APDU status bytes information
//-----------------------------------------------------------------------------

#include "apduinfo.h"

const APDUCode APDUCodeTable[] = {
	//  ID             Type                  Description
	{"XXXX", 	APDUCODE_TYPE_NONE,			""}, // blank string
	{"6---", 	APDUCODE_TYPE_ERROR,		"Class not supported."},
	{"61--", 	APDUCODE_TYPE_INFO,			"Response bytes still available"},
	{"61XX", 	APDUCODE_TYPE_INFO,			"Command successfully executed; 'XX' bytes of data are available and can be requested using GET RESPONSE."},
	{"62--", 	APDUCODE_TYPE_WARNING,		"State of non-volatile memory unchanged"},
	{"6200", 	APDUCODE_TYPE_WARNING,		"No information given (NV-Ram not changed)"},
	{"6201", 	APDUCODE_TYPE_WARNING,		"NV-Ram not changed 1."},
	{"6281", 	APDUCODE_TYPE_WARNING,		"Part of returned data may be corrupted"},
	{"6282", 	APDUCODE_TYPE_WARNING,		"End of file/record reached before reading Le bytes"},
	{"6283", 	APDUCODE_TYPE_WARNING,		"Selected file invalidated"},
	{"6284", 	APDUCODE_TYPE_WARNING,		"Selected file is not valid. FCI not formated according to ISO"},
	{"6285", 	APDUCODE_TYPE_WARNING,		"No input data available from a sensor on the card. No Purse Engine enslaved for R3bc"},
	{"62A2", 	APDUCODE_TYPE_WARNING,		"Wrong R-MAC"},
	{"62A4", 	APDUCODE_TYPE_WARNING,		"Card locked (during reset( ))"},
	{"62CX", 	APDUCODE_TYPE_WARNING,		"Counter with value x (command dependent)"},
	{"62F1", 	APDUCODE_TYPE_WARNING,		"Wrong C-MAC"},
	{"62F3", 	APDUCODE_TYPE_WARNING,		"Internal reset"},
	{"62F5", 	APDUCODE_TYPE_WARNING,		"Default agent locked"},
	{"62F7", 	APDUCODE_TYPE_WARNING,		"Cardholder locked"},
	{"62F8", 	APDUCODE_TYPE_WARNING,		"Basement is current agent"},
	{"62F9", 	APDUCODE_TYPE_WARNING,		"CALC Key Set not unblocked"},
	{"62FX", 	APDUCODE_TYPE_WARNING,		"-"},
	{"62XX", 	APDUCODE_TYPE_WARNING,		"RFU"},
	{"63--", 	APDUCODE_TYPE_WARNING,		"State of non-volatile memory changed"},
	{"6300", 	APDUCODE_TYPE_WARNING,		"No information given (NV-Ram changed)"},
	{"6381", 	APDUCODE_TYPE_WARNING,		"File filled up by the last write. Loading/updating is not allowed."},
	{"6382", 	APDUCODE_TYPE_WARNING,		"Card key not supported."},
	{"6383", 	APDUCODE_TYPE_WARNING,		"Reader key not supported."},
	{"6384", 	APDUCODE_TYPE_WARNING,		"Plaintext transmission not supported."},
	{"6385", 	APDUCODE_TYPE_WARNING,		"Secured transmission not supported."},
	{"6386", 	APDUCODE_TYPE_WARNING,		"Volatile memory is not available."},
	{"6387", 	APDUCODE_TYPE_WARNING,		"Non-volatile memory is not available."},
	{"6388", 	APDUCODE_TYPE_WARNING,		"Key number not valid."},
	{"6389", 	APDUCODE_TYPE_WARNING,		"Key length is not correct."},
	{"63C0", 	APDUCODE_TYPE_WARNING,		"Verify fail, no try left."},
	{"63C1", 	APDUCODE_TYPE_WARNING,		"Verify fail, 1 try left."},
	{"63C2", 	APDUCODE_TYPE_WARNING,		"Verify fail, 2 tries left."},
	{"63C3", 	APDUCODE_TYPE_WARNING,		"Verify fail, 3 tries left."},
	{"63CX", 	APDUCODE_TYPE_WARNING,		"The counter has reached the value 'x' (0 = x = 15) (command dependent)."},
	{"63F1", 	APDUCODE_TYPE_WARNING,		"More data expected."},
	{"63F2", 	APDUCODE_TYPE_WARNING,		"More data expected and proactive command pending."},
	{"63FX", 	APDUCODE_TYPE_WARNING,		"-"},
	{"63XX", 	APDUCODE_TYPE_WARNING,		"RFU"},
	{"64--", 	APDUCODE_TYPE_ERROR,		"State of non-volatile memory unchanged"},
	{"6400", 	APDUCODE_TYPE_ERROR,		"No information given (NV-Ram not changed)"},
	{"6401", 	APDUCODE_TYPE_ERROR,		"Command timeout. Immediate response required by the card."},
	{"64XX", 	APDUCODE_TYPE_ERROR,		"RFU"},
	{"65--", 	APDUCODE_TYPE_ERROR,		"State of non-volatile memory changed"},
	{"6500", 	APDUCODE_TYPE_ERROR,		"No information given"},
	{"6501", 	APDUCODE_TYPE_ERROR,		"Write error. Memory failure. There have been problems in writing or reading the EEPROM. Other hardware problems may also bring this error."},
	{"6581", 	APDUCODE_TYPE_ERROR,		"Memory failure"},
	{"65FX", 	APDUCODE_TYPE_ERROR,		"-"},
	{"65XX", 	APDUCODE_TYPE_ERROR,		"RFU"},
	{"66--", 	APDUCODE_TYPE_SECURITY,		" "},
	{"6600", 	APDUCODE_TYPE_SECURITY,		"Error while receiving (timeout)"},
	{"6601", 	APDUCODE_TYPE_SECURITY,		"Error while receiving (character parity error)"},
	{"6602", 	APDUCODE_TYPE_SECURITY,		"Wrong checksum"},
	{"6603", 	APDUCODE_TYPE_SECURITY,		"The current DF file without FCI"},
	{"6604", 	APDUCODE_TYPE_SECURITY,		"No SF or KF under the current DF"},
	{"6669", 	APDUCODE_TYPE_SECURITY,		"Incorrect Encryption/Decryption Padding"},
	{"66XX", 	APDUCODE_TYPE_SECURITY,		"-"},
	{"67--", 	APDUCODE_TYPE_ERROR,		" "},
	{"6700", 	APDUCODE_TYPE_ERROR,		"Wrong length"},
	{"67XX", 	APDUCODE_TYPE_ERROR,		"length incorrect (procedure)(ISO 7816-3)"},
	{"68--", 	APDUCODE_TYPE_ERROR,		"Functions in CLA not supported"},
	{"6800", 	APDUCODE_TYPE_ERROR,		"No information given (The request function is not supported by the card)"},
	{"6881", 	APDUCODE_TYPE_ERROR,		"Logical channel not supported"},
	{"6882", 	APDUCODE_TYPE_ERROR,		"Secure messaging not supported"},
	{"6883", 	APDUCODE_TYPE_ERROR,		"Last command of the chain expected"},
	{"6884", 	APDUCODE_TYPE_ERROR,		"Command chaining not supported"},
	{"68FX", 	APDUCODE_TYPE_ERROR,		"-"},
	{"68XX", 	APDUCODE_TYPE_ERROR,		"RFU"},
	{"69--", 	APDUCODE_TYPE_ERROR,		"Command not allowed"},
	{"6900", 	APDUCODE_TYPE_ERROR,		"No information given (Command not allowed)"},
	{"6901", 	APDUCODE_TYPE_ERROR,		"Command not accepted (inactive state)"},
	{"6981", 	APDUCODE_TYPE_ERROR,		"Command incompatible with file structure"},
	{"6982", 	APDUCODE_TYPE_ERROR,		"Security condition not satisfied."},
	{"6983", 	APDUCODE_TYPE_ERROR,		"Authentication method blocked"},
	{"6984", 	APDUCODE_TYPE_ERROR,		"Referenced data reversibly blocked (invalidated)"},
	{"6985", 	APDUCODE_TYPE_ERROR,		"Conditions of use not satisfied."},
	{"6986", 	APDUCODE_TYPE_ERROR,		"Command not allowed (no current EF)"},
	{"6987", 	APDUCODE_TYPE_ERROR,		"Expected secure messaging (SM) object missing"},
	{"6988", 	APDUCODE_TYPE_ERROR,		"Incorrect secure messaging (SM) data object"},
	{"698D", 	APDUCODE_TYPE_NONE, 		"Reserved"},
	{"6996", 	APDUCODE_TYPE_ERROR,		"Data must be updated again"},
	{"69E1", 	APDUCODE_TYPE_ERROR,		"POL1 of the currently Enabled Profile prevents this action."},
	{"69F0", 	APDUCODE_TYPE_ERROR,		"Permission Denied"},
	{"69F1", 	APDUCODE_TYPE_ERROR,		"Permission Denied - Missing Privilege"},
	{"69FX", 	APDUCODE_TYPE_ERROR,		"-"},
	{"69XX", 	APDUCODE_TYPE_ERROR,		"RFU"},
	{"6A--", 	APDUCODE_TYPE_ERROR,		"Wrong parameter(s) P1-P2"},
	{"6A00", 	APDUCODE_TYPE_ERROR,		"No information given (Bytes P1 and/or P2 are incorrect)"},
	{"6A80", 	APDUCODE_TYPE_ERROR,		"The parameters in the data field are incorrect."},
	{"6A81", 	APDUCODE_TYPE_ERROR,		"Function not supported"},
	{"6A82", 	APDUCODE_TYPE_ERROR,		"File not found"},
	{"6A83", 	APDUCODE_TYPE_ERROR,		"Record not found"},
	{"6A84", 	APDUCODE_TYPE_ERROR,		"There is insufficient memory space in record or file"},
	{"6A85", 	APDUCODE_TYPE_ERROR,		"Lc inconsistent with TLV structure"},
	{"6A86", 	APDUCODE_TYPE_ERROR,		"Incorrect P1 or P2 parameter."},
	{"6A87", 	APDUCODE_TYPE_ERROR,		"Lc inconsistent with P1-P2"},
	{"6A88", 	APDUCODE_TYPE_ERROR,		"Referenced data not found"},
	{"6A89", 	APDUCODE_TYPE_ERROR,		"File already exists"},
	{"6A8A", 	APDUCODE_TYPE_ERROR,		"DF name already exists."},
	{"6AF0", 	APDUCODE_TYPE_ERROR,		"Wrong parameter value"},
	{"6AFX", 	APDUCODE_TYPE_ERROR,		"-"},
	{"6AXX", 	APDUCODE_TYPE_ERROR,		"RFU"},
	{"6B--", 	APDUCODE_TYPE_ERROR,		" "},
	{"6B00", 	APDUCODE_TYPE_ERROR,		"Wrong parameter(s) P1-P2"},
	{"6BXX", 	APDUCODE_TYPE_ERROR,		"Reference incorrect (procedure byte), (ISO 7816-3)"},
	{"6C--", 	APDUCODE_TYPE_ERROR,		"Wrong length Le"},
	{"6C00", 	APDUCODE_TYPE_ERROR,		"Incorrect P3 length."},
	{"6CXX", 	APDUCODE_TYPE_ERROR,		"Bad length value in Le; 'xx' is the correct exact Le"},
	{"6D--", 	APDUCODE_TYPE_ERROR,		" "},
	{"6D00", 	APDUCODE_TYPE_ERROR,		"Instruction code not supported or invalid"},
	{"6DXX", 	APDUCODE_TYPE_ERROR,		"Instruction code not programmed or invalid (procedure byte), (ISO 7816-3)"},
	{"6E--", 	APDUCODE_TYPE_ERROR,		" "},
	{"6E00", 	APDUCODE_TYPE_ERROR,		"Class not supported"},
	{"6EXX", 	APDUCODE_TYPE_ERROR,		"Instruction class not supported (procedure byte), (ISO 7816-3)"},
	{"6F--", 	APDUCODE_TYPE_ERROR,		"Internal exception"},
	{"6F00", 	APDUCODE_TYPE_ERROR,		"Command aborted - more exact diagnosis not possible (e.g., operating system error)."},
	{"6FFF", 	APDUCODE_TYPE_ERROR,		"Card dead (overuse, ...)"},
	{"6FXX", 	APDUCODE_TYPE_ERROR,		"No precise diagnosis (procedure byte), (ISO 7816-3)"},
	{"9---", 	APDUCODE_TYPE_NONE, 		""},
	{"9000", 	APDUCODE_TYPE_INFO,			"Command successfully executed (OK)."},
	{"9004", 	APDUCODE_TYPE_WARNING,		"PIN not succesfully verified, 3 or more PIN tries left"},
	{"9008", 	APDUCODE_TYPE_NONE, 		"Key/file not found"},
	{"9080", 	APDUCODE_TYPE_WARNING,		"Unblock Try Counter has reached zero"},
	{"9100", 	APDUCODE_TYPE_NONE, 		"OK"},
	{"9101", 	APDUCODE_TYPE_NONE, 		"States.activity, States.lock Status or States.lockable has wrong value"},
	{"9102", 	APDUCODE_TYPE_NONE, 		"Transaction number reached its limit"},
	{"910C", 	APDUCODE_TYPE_NONE, 		"No changes"},
	{"910E", 	APDUCODE_TYPE_NONE, 		"Insufficient NV-Memory to complete command"},
	{"911C", 	APDUCODE_TYPE_NONE, 		"Command code not supported"},
	{"911E", 	APDUCODE_TYPE_NONE, 		"CRC or MAC does not match data"},
	{"9140", 	APDUCODE_TYPE_NONE, 		"Invalid key number specified"},
	{"917E", 	APDUCODE_TYPE_NONE, 		"Length of command string invalid"},
	{"919D", 	APDUCODE_TYPE_NONE, 		"Not allow the requested command"},
	{"919E", 	APDUCODE_TYPE_NONE, 		"Value of the parameter invalid"},
	{"91A0", 	APDUCODE_TYPE_NONE, 		"Requested AID not present on PICC"},
	{"91A1", 	APDUCODE_TYPE_NONE, 		"Unrecoverable error within application"},
	{"91AE", 	APDUCODE_TYPE_NONE, 		"Authentication status does not allow the requested command"},
	{"91AF", 	APDUCODE_TYPE_NONE, 		"Additional data frame is expected to be sent"},
	{"91BE", 	APDUCODE_TYPE_NONE, 		"Out of boundary"},
	{"91C1", 	APDUCODE_TYPE_NONE, 		"Unrecoverable error within PICC"},
	{"91CA", 	APDUCODE_TYPE_NONE, 		"Previous Command was not fully completed"},
	{"91CD", 	APDUCODE_TYPE_NONE, 		"PICC was disabled by an unrecoverable error"},
	{"91CE", 	APDUCODE_TYPE_NONE, 		"Number of Applications limited to 28"},
	{"91DE", 	APDUCODE_TYPE_NONE, 		"File or application already exists"},
	{"91EE", 	APDUCODE_TYPE_NONE, 		"Could not complete NV-write operation due to loss of power"},
	{"91F0", 	APDUCODE_TYPE_NONE, 		"Specified file number does not exist"},
	{"91F1", 	APDUCODE_TYPE_NONE, 		"Unrecoverable error within file"},
	{"920x", 	APDUCODE_TYPE_INFO,			"Writing to EEPROM successful after 'x' attempts."},
	{"9210", 	APDUCODE_TYPE_ERROR,		"Insufficient memory. No more storage available."},
	{"9240", 	APDUCODE_TYPE_ERROR,		"Writing to EEPROM not successful."},
	{"9301", 	APDUCODE_TYPE_NONE, 		"Integrity error"},
	{"9302", 	APDUCODE_TYPE_NONE, 		"Candidate S2 invalid"},
	{"9303", 	APDUCODE_TYPE_ERROR,		"Application is permanently locked"},
	{"9400", 	APDUCODE_TYPE_ERROR,		"No EF selected."},
	{"9401", 	APDUCODE_TYPE_NONE, 		"Candidate currency code does not match purse currency"},
	{"9402", 	APDUCODE_TYPE_NONE, 		"Candidate amount too high"},
	{"9402", 	APDUCODE_TYPE_ERROR,		"Address range exceeded."},
	{"9403", 	APDUCODE_TYPE_NONE, 		"Candidate amount too low"},
	{"9404", 	APDUCODE_TYPE_ERROR,		"FID not found, record not found or comparison pattern not found."},
	{"9405", 	APDUCODE_TYPE_NONE, 		"Problems in the data field"},
	{"9406", 	APDUCODE_TYPE_ERROR,		"Required MAC unavailable"},
	{"9407", 	APDUCODE_TYPE_NONE, 		"Bad currency : purse engine has no slot with R3bc currency"},
	{"9408", 	APDUCODE_TYPE_NONE, 		"R3bc currency not supported in purse engine"},
	{"9408", 	APDUCODE_TYPE_ERROR,		"Selected file type does not match command."},
	{"9580", 	APDUCODE_TYPE_NONE, 		"Bad sequence"},
	{"9681", 	APDUCODE_TYPE_NONE, 		"Slave not found"},
	{"9700", 	APDUCODE_TYPE_NONE, 		"PIN blocked and Unblock Try Counter is 1 or 2"},
	{"9702", 	APDUCODE_TYPE_NONE, 		"Main keys are blocked"},
	{"9704", 	APDUCODE_TYPE_NONE, 		"PIN not succesfully verified, 3 or more PIN tries left"},
	{"9784", 	APDUCODE_TYPE_NONE, 		"Base key"},
	{"9785", 	APDUCODE_TYPE_NONE, 		"Limit exceeded - C-MAC key"},
	{"9786", 	APDUCODE_TYPE_NONE, 		"SM error - Limit exceeded - R-MAC key"},
	{"9787", 	APDUCODE_TYPE_NONE, 		"Limit exceeded - sequence counter"},
	{"9788", 	APDUCODE_TYPE_NONE, 		"Limit exceeded - R-MAC length"},
	{"9789", 	APDUCODE_TYPE_NONE, 		"Service not available"},
	{"9802", 	APDUCODE_TYPE_ERROR,		"No PIN defined."},
	{"9804", 	APDUCODE_TYPE_ERROR,		"Access conditions not satisfied, authentication failed."},
	{"9835", 	APDUCODE_TYPE_ERROR,		"ASK RANDOM or GIVE RANDOM not executed."},
	{"9840", 	APDUCODE_TYPE_ERROR,		"PIN verification not successful."},
	{"9850", 	APDUCODE_TYPE_ERROR,		"INCREASE or DECREASE could not be executed because a limit has been reached."},
	{"9862", 	APDUCODE_TYPE_ERROR,		"Authentication Error, application specific (incorrect MAC)"},
	{"9900", 	APDUCODE_TYPE_NONE, 		"1 PIN try left"},
	{"9904", 	APDUCODE_TYPE_NONE, 		"PIN not succesfully verified, 1 PIN try left"},
	{"9985", 	APDUCODE_TYPE_NONE, 		"Wrong status - Cardholder lock"},
	{"9986", 	APDUCODE_TYPE_ERROR,		"Missing privilege"},
	{"9987", 	APDUCODE_TYPE_NONE, 		"PIN is not installed"},
	{"9988", 	APDUCODE_TYPE_NONE, 		"Wrong status - R-MAC state"},
	{"9A00", 	APDUCODE_TYPE_NONE, 		"2 PIN try left"},
	{"9A04", 	APDUCODE_TYPE_NONE, 		"PIN not succesfully verified, 2 PIN try left"},
	{"9A71", 	APDUCODE_TYPE_NONE, 		"Wrong parameter value - Double agent AID"},
	{"9A72", 	APDUCODE_TYPE_NONE, 		"Wrong parameter value - Double agent Type"},
	{"9D05", 	APDUCODE_TYPE_ERROR,		"Incorrect certificate type"},
	{"9D07", 	APDUCODE_TYPE_ERROR,		"Incorrect session data size"},
	{"9D08", 	APDUCODE_TYPE_ERROR,		"Incorrect DIR file record size"},
	{"9D09", 	APDUCODE_TYPE_ERROR,		"Incorrect FCI record size"},
	{"9D0A", 	APDUCODE_TYPE_ERROR,		"Incorrect code size"},
	{"9D10", 	APDUCODE_TYPE_ERROR,		"Insufficient memory to load application"},
	{"9D11", 	APDUCODE_TYPE_ERROR,		"Invalid AID"},
	{"9D12", 	APDUCODE_TYPE_ERROR,		"Duplicate AID"},
	{"9D13", 	APDUCODE_TYPE_ERROR,		"Application previously loaded"},
	{"9D14", 	APDUCODE_TYPE_ERROR,		"Application history list full"},
	{"9D15", 	APDUCODE_TYPE_ERROR,		"Application not open"},
	{"9D17", 	APDUCODE_TYPE_ERROR,		"Invalid offset"},
	{"9D18", 	APDUCODE_TYPE_ERROR,		"Application already loaded"},
	{"9D19", 	APDUCODE_TYPE_ERROR,		"Invalid certificate"},
	{"9D1A", 	APDUCODE_TYPE_ERROR,		"Invalid signature"},
	{"9D1B", 	APDUCODE_TYPE_ERROR,		"Invalid KTU"},
	{"9D1D", 	APDUCODE_TYPE_ERROR,		"MSM controls not set"},
	{"9D1E", 	APDUCODE_TYPE_ERROR,		"Application signature does not exist"},
	{"9D1F", 	APDUCODE_TYPE_ERROR,		"KTU does not exist"},
	{"9D20", 	APDUCODE_TYPE_ERROR,		"Application not loaded"},
	{"9D21", 	APDUCODE_TYPE_ERROR,		"Invalid Open command data length"},
	{"9D30", 	APDUCODE_TYPE_ERROR,		"Check data parameter is incorrect (invalid start address)"},
	{"9D31", 	APDUCODE_TYPE_ERROR,		"Check data parameter is incorrect (invalid length)"},
	{"9D32", 	APDUCODE_TYPE_ERROR,		"Check data parameter is incorrect (illegal memory check area)"},
	{"9D40", 	APDUCODE_TYPE_ERROR,		"Invalid MSM Controls ciphertext"},
	{"9D41", 	APDUCODE_TYPE_ERROR,		"MSM controls already set"},
	{"9D42", 	APDUCODE_TYPE_ERROR,		"Set MSM Controls data length less than 2 bytes"},
	{"9D43", 	APDUCODE_TYPE_ERROR,		"Invalid MSM Controls data length"},
	{"9D44", 	APDUCODE_TYPE_ERROR,		"Excess MSM Controls ciphertext"},
	{"9D45", 	APDUCODE_TYPE_ERROR,		"Verification of MSM Controls data failed"},
	{"9D50", 	APDUCODE_TYPE_ERROR,		"Invalid MCD Issuer production ID"},
	{"9D51", 	APDUCODE_TYPE_ERROR,		"Invalid MCD Issuer ID"},
	{"9D52", 	APDUCODE_TYPE_ERROR,		"Invalid set MSM controls data date"},
	{"9D53", 	APDUCODE_TYPE_ERROR,		"Invalid MCD number"},
	{"9D54", 	APDUCODE_TYPE_ERROR,		"Reserved field error"},
	{"9D55", 	APDUCODE_TYPE_ERROR,		"Reserved field error"},
	{"9D56", 	APDUCODE_TYPE_ERROR,		"Reserved field error"},
	{"9D57", 	APDUCODE_TYPE_ERROR,		"Reserved field error"},
	{"9D60", 	APDUCODE_TYPE_ERROR,		"MAC verification failed"},
	{"9D61", 	APDUCODE_TYPE_ERROR,		"Maximum number of unblocks reached"},
	{"9D62", 	APDUCODE_TYPE_ERROR,		"Card was not blocked"},
	{"9D63", 	APDUCODE_TYPE_ERROR,		"Crypto functions not available"},
	{"9D64", 	APDUCODE_TYPE_ERROR,		"No application loaded"},
	{"9E00", 	APDUCODE_TYPE_NONE, 		"PIN not installed"},
	{"9E04", 	APDUCODE_TYPE_NONE, 		"PIN not succesfully verified, PIN not installed"},
	{"9F00", 	APDUCODE_TYPE_NONE, 		"PIN blocked and Unblock Try Counter is 3"},
	{"9F04", 	APDUCODE_TYPE_NONE, 		"PIN not succesfully verified, PIN blocked and Unblock Try Counter is 3"},
	{"9FXX", 	APDUCODE_TYPE_NONE, 		"Command successfully executed; 'xx' bytes of data are available and can be requested using GET RESPONSE."},
	{"9XXX", 	APDUCODE_TYPE_NONE, 		"Application related status, (ISO 7816-3)"}
};
const size_t APDUCodeTableLen = sizeof(APDUCodeTable)/sizeof(APDUCode);

int CodeCmp(const char *code1, const char *code2) {
	int xsymb = 0;
	int cmp = 0;
	for (int i = 0; i < 4; i++) {
		if (code1[i] == code2[i])
			cmp++;
		if (code1[i] == 'X' || code2[i] == 'X')
			xsymb++;
	}
	if (cmp == 4)
		return 0;
	
	if (cmp + xsymb == 4)
		return xsymb;
	
	return -1;
}

const APDUCode* const GetAPDUCode(uint8_t sw1, uint8_t sw2) {
	char buf[5] = {0};
	int res;
	int mineq = APDUCodeTableLen;
	int mineqindx = 0;
	
	sprintf(buf, "%02X%02X", sw1, sw2);
	
	for (int i = 0; i < APDUCodeTableLen; i++) {
		res = CodeCmp(APDUCodeTable[i].ID, buf);
		
		// equal
		if (res == 0) { 
			return &APDUCodeTable[i];
		}
		
		// with some  'X'
		if (res > 0 && mineq > res) {
			mineq = res;
			mineqindx = i;
		}
	}

	// if we have not equal, but with some 'X'
	if (mineqindx < APDUCodeTableLen) {
		return &APDUCodeTable[mineqindx];
	}
	
	return NULL;
}

const char* GetAPDUCodeDescription(uint8_t sw1, uint8_t sw2) {
	const APDUCode *cd = GetAPDUCode(sw1, sw2);
	if (cd)
		return cd->Description;
	else
		return APDUCodeTable[0].Description; //empty string
}
